﻿using System;
using System.Configuration;
using System.Reflection;
using System.Xml;

namespace CID.Execution.Support.DeploymentInitiation.Configuration
{
    public class DeploymentInitiationServiceConfiguratorElement : ConfigurationElement
    {
        private const string TypeNameAttribute = "typeName";

        public Type Type { get; private set; }

        public XmlDocument Configuration { get; private set; }

        private ConstructorInfo Constructor { get; set; }

        protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
        {
            try
            {
                var typeName = reader.GetAttribute(TypeNameAttribute);
                var configurationXml = reader.ReadElementContentAsString();
                Configuration = new XmlDocument();
                Configuration.LoadXml(configurationXml);
                Type = LoadConfiguratorType(typeName);
            }
            catch (Exception ex)
            {
                throw new InvalidDeploymentInitiationServiceConfigurationException(ex);
            }
        }

        private Type LoadConfiguratorType(string typeName)
        {
            var result = Type.GetType(typeName, true);
            if (!typeof(IDeploymentInitiationServiceConfigurator).IsAssignableFrom(result))
                throw new InvalidCastException(String.Format("The type {0} is not a valid IDeploymentInitiationServiceConfigurator", typeName));
            Constructor = result.GetConstructor(new Type[] { typeof(XmlElement) });
            if (Constructor == null)
                throw new Exception(String.Format("The type {0} is not a valid IDeploymentInitiationServiceConfigurator", typeName));
            return result;
        }

        public IDeploymentInitiationServiceConfigurator GetConfigurator()
        {
            return Constructor.Invoke(new object[] { Configuration.DocumentElement }) as IDeploymentInitiationServiceConfigurator;
        }
    }
}
